home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / pcutils / os2 / rt / sil.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  5KB  |  187 lines

  1. /*
  2.  
  3. SIL.C  Simple intersection lists
  4.  
  5. */
  6.  
  7. /*...sincludes:0:*/
  8. #include <stdlib.h>
  9. #include <stddef.h>
  10. #include <memory.h>
  11. #include <math.h>
  12. #include "standard.h"
  13. #include "rt.h"
  14. #include "vector.h"
  15. #define    _SIL_
  16. #include "sil.h"
  17.  
  18. /*...vrt\46\h:0:*/
  19. /*...vvector\46\h:0:*/
  20. /*...vsil\46\h:0:*/
  21. /*...e*/
  22.  
  23. #define    ZERO(x) ( ((x)>=-1.0e-10) && ((x)<=1.0e-10) )
  24. #define    SIDESTEP (1.0e6)
  25.  
  26. /*...sintersect_linear_t:0:*/
  27. void    intersect_linear_t(
  28.     double coeff_of_t, double constant_term,
  29.     VECTOR p, VECTOR q,
  30.     void *shapeinfo, double (*value_of_shape)(void *shapeinfo, VECTOR v),
  31.     SIL *sil
  32.     )
  33.     {
  34.     if ( ZERO(coeff_of_t) )
  35.         /* No intersection with solid surface */
  36.         {
  37.         if ( (*value_of_shape)(shapeinfo, p) <= 0.0 )
  38.             /* Completely in solid */
  39.             {
  40.             sil->n_sis            = 2;
  41.             sil->sis[0].t        = -INFINITE;
  42.             sil->sis[0].entering = TRUE;
  43.             sil->sis[1].t        = INFINITE;
  44.             sil->sis[1].entering = FALSE;
  45.             }
  46.         else
  47.             /* Completely out of solid */
  48.             sil->n_sis            = 0;
  49.         }
  50.     else
  51.         /* Intersects solid exactly once */
  52.         {
  53.         double t = - constant_term / coeff_of_t;
  54.  
  55.         sil->n_sis            = 2;
  56.         sil->sis[0].entering = TRUE;
  57.         sil->sis[1].entering = FALSE;
  58.  
  59.         if ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t+SIDESTEP)) <= 0.0 )
  60.             /* Entering solid */
  61.             {
  62.             sil->sis[0].t = t;
  63.             sil->sis[1].t = INFINITE;
  64.             }
  65.         else
  66.             /* Leaving solid */
  67.             {
  68.             sil->sis[0].t = -INFINITE;
  69.             sil->sis[1].t = t;
  70.             }
  71.         }
  72.     }
  73. /*...e*/
  74. /*...sintersect_quadratic_t:0:*/
  75. void    intersect_quadratic_t(
  76.     double qa, double qb, double qc,
  77.     VECTOR p, VECTOR q,
  78.     void *shapeinfo, double (*value_of_shape)(void *shapeinfo, VECTOR v),
  79.     SIL *sil
  80.     )
  81.     {
  82.     double    qs;
  83.  
  84.     if ( ZERO(qa) )
  85. /*...sdo linear case:16:*/
  86. intersect_linear_t(qb, qc, p, q, shapeinfo, value_of_shape, sil);
  87. /*...e*/
  88.     else if ( (qs = qb*qb - 4.0*qa*qc) < 0.0 )
  89. /*...sno real roots:16:*/
  90. /* No real roots => no intersections, all solid or all empty */
  91. {
  92. if ( (*value_of_shape)(shapeinfo, p) <= 0.0 )
  93.     {
  94.     sil->n_sis            = 2;
  95.     sil->sis[0].t        = -INFINITE;
  96.     sil->sis[0].entering = TRUE;
  97.     sil->sis[1].t        = INFINITE;
  98.     sil->sis[1].entering = FALSE;
  99.     }
  100. else
  101.     sil->n_sis = 0;
  102. }
  103. /*...e*/
  104.     else if ( ZERO(qs) )
  105. /*...sone double root:16:*/
  106. {
  107. double    t = -qb / (qa + qa);
  108. BOOLEAN from_inside = ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t-SIDESTEP)) <= 0.0 );
  109. BOOLEAN to_inside   = ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t+SIDESTEP)) <= 0.0 );
  110.  
  111. #define    DUAL_SWITCH(f,t)    (((f)<<1)+(t))
  112.  
  113. switch ( DUAL_SWITCH(from_inside, to_inside) )
  114.     {
  115.     case DUAL_SWITCH(FALSE, FALSE):        /* Grazing surface */
  116.         sil->n_sis            = 0;
  117.         break;
  118.     case DUAL_SWITCH(FALSE,  TRUE):        /* Entering solid area */
  119.         sil->n_sis            = 2;
  120.         sil->sis[0].t        = t;
  121.         sil->sis[0].entering = TRUE;
  122.         sil->sis[1].t        = INFINITE;
  123.         sil->sis[1].entering = FALSE;
  124.         break;
  125.     case DUAL_SWITCH( TRUE, FALSE):        /* Leaving solid area */
  126.         sil->n_sis            = 2;
  127.         sil->sis[0].t        = -INFINITE;
  128.         sil->sis[0].entering = TRUE;
  129.         sil->sis[1].t        = t;
  130.         sil->sis[1].entering = FALSE;
  131.         break;
  132.     case DUAL_SWITCH( TRUE,  TRUE):        /* Never left solid area */
  133.         sil->n_sis            = 2;
  134.         sil->sis[0].t        = -INFINITE;
  135.         sil->sis[0].entering = TRUE;
  136.         sil->sis[1].t        = INFINITE;
  137.         sil->sis[1].entering = FALSE;
  138.         break;
  139.     }
  140. }
  141. /*...e*/
  142.     else
  143. /*...stwo roots:16:*/
  144. /*
  145. Where I say t1-SIDESTEP, I used to say the more obvious (t1+t2)*0.5.
  146. I changed it because if t1 and t2 are very close, inaccuracies in the
  147. arithmetic can cause the value of shape evaluated at (t1+t2)*0.5 to be just the
  148. wrong side of 0.0. The newer test is much more likely to give the right result
  149. as we are now evaluating the shape function further away from any roots.
  150. */
  151.  
  152. {
  153. double    rooted = sqrt(qs);
  154. double    t1 = (-qb - rooted) / (qa + qa);
  155. double    t2 = (-qb + rooted) / (qa + qa);
  156.  
  157. if ( t1 > t2 )
  158.     /* Ensure t1 is lower than t2 */
  159.     { double t = t1; t1 = t2; t2 = t; }
  160.  
  161. if ( (*value_of_shape)(shapeinfo, t_along_pq(p, q, t1-SIDESTEP)) > 0.0 )
  162.     /* Middle part is the solid part */
  163.     {
  164.     sil->n_sis            = 2;
  165.     sil->sis[0].t        = t1;
  166.     sil->sis[0].entering = TRUE;
  167.     sil->sis[1].t        = t2;
  168.     sil->sis[1].entering = FALSE;
  169.     }
  170. else
  171.     /* Regions before and after middle part are the solid parts */
  172.     {
  173.     sil->n_sis            = 4;
  174.     sil->sis[0].t        = -INFINITE;
  175.     sil->sis[0].entering = TRUE;
  176.     sil->sis[1].t        = t1;
  177.     sil->sis[1].entering = FALSE;
  178.     sil->sis[2].t        = t2;
  179.     sil->sis[2].entering = TRUE;
  180.     sil->sis[3].t        = INFINITE;
  181.     sil->sis[3].entering = FALSE;
  182.     }
  183. }
  184. /*...e*/
  185.     }
  186. /*...e*/
  187.